package com.zhiche.wms.service.opbaas.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import com.google.common.collect.Maps;
import com.lisa.date.DateTime;
import com.lisa.date.DateUtil;
import com.zhiche.wms.configuration.MyConfigurationProperties;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.RestfulResponse;
import com.zhiche.wms.core.supports.enums.InterfaceAddrEnum;
import com.zhiche.wms.core.supports.enums.InterfaceEventEnum;
import com.zhiche.wms.core.supports.enums.InterfaceVisitTypeEnum;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.HttpClientUtil;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.domain.mapper.inbound.InboundNoticeHeaderMapper;
import com.zhiche.wms.domain.mapper.inbound.InboundNoticeLineMapper;
import com.zhiche.wms.domain.mapper.inbound.InboundPutawayLineMapper;
import com.zhiche.wms.domain.mapper.log.ItfExplogLineMapper;
import com.zhiche.wms.domain.mapper.otm.OtmOrderReleaseMapper;
import com.zhiche.wms.domain.mapper.otm.OtmShipmentMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundNoticeHeaderMapper;
import com.zhiche.wms.domain.model.inbound.InboundNoticeHeader;
import com.zhiche.wms.domain.model.inbound.InboundNoticeLine;
import com.zhiche.wms.domain.model.inbound.InboundPutawayLine;
import com.zhiche.wms.domain.model.log.ItfExplogLine;
import com.zhiche.wms.domain.model.opbaas.ExceptionRegister;
import com.zhiche.wms.domain.model.opbaas.StatusLog;
import com.zhiche.wms.domain.model.otm.OtmCancleShipment;
import com.zhiche.wms.domain.model.otm.OtmOrderRelease;
import com.zhiche.wms.domain.model.otm.OtmShipment;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeHeader;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeLine;
import com.zhiche.wms.domain.model.outbound.OutboundShipLine;
import com.zhiche.wms.domain.model.sys.User;
import com.zhiche.wms.dto.opbaas.paramdto.AppCommonQueryDTO;
import com.zhiche.wms.dto.opbaas.paramdto.OrderReleaseParamDTO;
import com.zhiche.wms.dto.opbaas.resultdto.*;
import com.zhiche.wms.service.common.IntegrationService;
import com.zhiche.wms.service.constant.PutAwayType;
import com.zhiche.wms.service.constant.SourceSystem;
import com.zhiche.wms.service.dto.OTMEvent;
import com.zhiche.wms.service.opbaas.*;
import com.zhiche.wms.service.otm.IOtmOrderReleaseService;
import com.zhiche.wms.service.otm.IOtmShipmentService;
import com.zhiche.wms.service.outbound.IOutboundNoticeLineService;
import com.zhiche.wms.service.outbound.IOutboundPrepareHeaderService;
import com.zhiche.wms.service.outbound.IOutboundShipLineService;
import com.zhiche.wms.service.stock.ISkuService;
import com.zhiche.wms.service.sys.IUserDeliveryPointService;
import com.zhiche.wms.service.sys.IUserService;
import com.zhiche.wms.service.utils.BusinessNodeExport;
import com.zhiche.wms.service.utils.CommonMethod;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 运单 服务实现类
 * </p>
 *
 * @author user
 * @since 2018-05-24
 */
@Service
public class OrderReleaseServiceImpl extends ServiceImpl<OtmOrderReleaseMapper, OtmOrderRelease> implements IOrderReleaseService {
    private static final Logger LOGGER = LoggerFactory.getLogger(OrderReleaseServiceImpl.class);
    @Autowired
    private IUserService userService;
    @Autowired
    private IntegrationService integrationService;
    @Autowired
    private IOtmShipmentService shipmentService;
    @Autowired
    private BusinessNodeExport nodeExport;
    @Autowired
    private IStatusLogService statusLogService;
    @Autowired
    private IOutboundNoticeLineService outboundNoticeLineService;
    @Autowired
    private IOutboundShipLineService outboundShipLineService;
    @Autowired
    private IOutboundPrepareHeaderService prepareHeaderService;
    @Autowired
    private IUserDeliveryPointService userDeliveryPointService;
    @Autowired
    private IDeliveryPointService deliveryPointService;
    @Autowired
    private ExceptionToOTMService exceptionToOTMService;
    @Autowired
    private IExceptionRegisterService exceptionRegisterService;
    @Autowired
    private MyConfigurationProperties properties;
    @Autowired
    private IOtmShipmentService otmShipmentService;
    @Autowired
    private IOtmOrderReleaseService otmOrderReleaseService;
    @Autowired
    private OtmShipmentMapper otmShipmentMapper;
    @Autowired
    private ItfExplogLineMapper itfExplogLineMapper;
    @Autowired
    private OutboundNoticeHeaderMapper outboundNoticeHeaderMapper;
    @Autowired
    private InboundNoticeHeaderMapper inboundNoticeHeaderMapper;
    @Autowired
    private InboundNoticeLineMapper inboundNoticeLineMapper;
    @Autowired
    private ISkuService iSkuService;
    @Autowired
    private InboundPutawayLineMapper inboundPutawayLineMapper;
    @Autowired
    private SnowFlakeId flakeId;


    @Override
    public Page<OrderReleaseParamDTO> queryOrderReleaseList(Page<OrderReleaseParamDTO> page) {
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }

        List<String> opDeliveryPoints = deliveryPointService.queryOpdeliveryPoint(loginUser.getId());
        if (CollectionUtils.isEmpty(opDeliveryPoints)) {
            throw new BaseException("未配置发车点,不能进行此操作");
        }

        Wrapper<OrderReleaseParamDTO> ew = new EntityWrapper<>();
        Map<String, Object> condition = page.getCondition();
        ew.in("origin_location_gid", opDeliveryPoints);
        if (condition != null) {
            if (condition.containsKey("boundType") && Objects.nonNull(condition.get("boundType"))) {
                ew.eq("bound_type", condition.get("boundType"));
            }
            if (condition.containsKey("plateNo") && Objects.nonNull(condition.get("plateNo"))) {
                ew.like("plate_no", condition.get("plateNo").toString());
            }
            if (condition.containsKey("originLocationName") && Objects.nonNull(condition.get("originLocationName"))) {
                ew.like("origin_location_name", condition.get("originLocationName").toString());
            }
            if (condition.containsKey("destLocationName") && Objects.nonNull(condition.get("destLocationName"))) {
                ew.like("dest_location_name", condition.get("destLocationName").toString());
            }
            if (condition.containsKey("shipmentGid") && Objects.nonNull(condition.get("shipmentGid"))) {
                ew.like("shipment_gid", condition.get("shipmentGid").toString());
            }
            if (condition.containsKey("startDate") && Objects.nonNull(condition.get("startDate"))) {
                ew.ge("gmt_create", condition.get("startDate").toString());
            }
            if (condition.containsKey("endDate") && Objects.nonNull(condition.get("endDate"))) {
                ew.le("gmt_create", condition.get("endDate").toString());
            }
            if (condition.containsKey("vin") && Objects.nonNull(condition.get("vin"))) {
                String vin = condition.get("vin").toString();
                List<String> vins = Arrays.asList(CommonMethod.setVins(vin));
                ew.andNew().in("vin", vins).or().like("vin", vin);
            }
        }
        ew.ne("shipmentStatus", TableStatusEnum.STATUS_50.getCode());
        ew.orderBy("gmt_create");
        List<OrderReleaseParamDTO> dtoList = this.baseMapper.queryOrderReleaseList(page, ew);
        page.setRecords(dtoList);
        return page;
    }

    /**
     * 装车交验 - 查询列表
     */
    @Override
    public Page<ReleaseWithShipmentDTO> queryReleaseShipList(Page<ReleaseWithShipmentDTO> page) {
        if (page == null) {
            throw new BaseException("参数page不能为空");
        }
        Map<String, Object> condition = page.getCondition();
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        Object key = condition.get("key");
        if (key == null || StringUtils.isBlank(key.toString())) {
            throw new BaseException("查询参数不能为空");
        }
        EntityWrapper<ReleaseWithShipmentDTO> ew = new EntityWrapper<>();
        ew.isNotNull("userId")
                .eq("is_ship", TableStatusEnum.STATUS_1.getCode())
                .ne("status", TableStatusEnum.STATUS_50.getCode())
                .eq("userCode", loginUser.getCode())
                .andNew()
                .like("cus_order_no", key.toString())
                .or()
                .like("shipment_gid", key.toString())
                .or()
                .like("cus_waybill_no", key.toString())
                .or()
                .like("vin", key.toString())
                .orderBy("gmt_create", false)
                .orderBy("id", false);
        List<ReleaseWithShipmentDTO> data = baseMapper.queryReleaseShipList(page, ew);
        if (CollectionUtils.isEmpty(data)) {
            throw new BaseException("为查询到对应发运数据");
        }
        page.setRecords(data);
        return page;
    }

    /**
     * 查询装车发运详细信息
     */
    @Override
    public ReleaseWithShipmentDTO getReleaseShipDetail(AppCommonQueryDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        Map<String, String> condition = dto.getCondition();
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("查询参数不能为空");
        }
        String visitType = condition.get("visitType");
        String key = condition.get("key");
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        if (StringUtils.isBlank(visitType)) {
            throw new BaseException("访问方式不能为空");
        }
        if (StringUtils.isBlank(key)) {
            throw new BaseException("key不能为空");
        }
        if (InterfaceVisitTypeEnum.CLICK_TYPE.getCode().equals(visitType)) {
            ReleaseWithShipmentDTO detailClick = getDetailClick(key, loginUser);
            String send = exceptionToOTMService.isSend(detailClick.getVin(), detailClick.getOriginLocationName());
            if (StringUtils.isNotBlank(send)) detailClick.setIsCanSend(send);
            return detailClick;
        } else if (InterfaceVisitTypeEnum.SCAN_TYPE.getCode().equals(visitType)) {
            //支持qrCode 车架号  订单号 扫码
            ReleaseWithShipmentDTO detailScan = getDetailScan(key, loginUser);
            String send = exceptionToOTMService.isSend(detailScan.getVin(), detailScan.getOriginLocationName());
            if (StringUtils.isNotBlank(send)) detailScan.setIsCanSend(send);
            return detailScan;
        } else {
            throw new BaseException("不支持的访问方式");
        }
    }

    /**
     * 装车交验确认
     */
    @Override
    public OtmOrderRelease updateReleaseShip(AppCommonQueryDTO dto){
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        Map<String, String> condition = dto.getCondition();
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("查询参数不能为空");
        }
        String key = condition.get("key");
        if (StringUtils.isBlank(key)) {
            throw new BaseException("key不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        OtmOrderRelease release = selectById(Long.valueOf(key));
        if (release == null) {
            throw new BaseException("未查询到Key" + key + "的运单信息");
        }
        if (TableStatusEnum.STATUS_WMS_HANDOVER.getCode().equals(release.getStatus())) {
            throw new BaseException("运单" + key + "已经交验,无需重复操作");
        }
        OtmOrderRelease oor = new OtmOrderRelease();
        oor.setStatus(TableStatusEnum.STATUS_WMS_HANDOVER.getCode());
        oor.setId(release.getId());
        updateById(oor);
        release.setStatus(TableStatusEnum.STATUS_WMS_HANDOVER.getCode());
        new Thread(() -> {
            StatusLog sl = new StatusLog();
            sl.setTableType(TableStatusEnum.STATUS_10.getCode());
            sl.setTableId(String.valueOf(release.getId()));
            sl.setStatus(TableStatusEnum.STATUS_WMS_HANDOVER.getCode());
            sl.setStatusName(TableStatusEnum.STATUS_WMS_HANDOVER.getCode());
            sl.setUserCreate(loginUser.getName());
            statusLogService.insert(sl);
        }).start();
        return release;
    }

    /**
     * 装车发运 - 模糊搜索查询
     */
    @Override
    public Page<ShipmentForShipDTO> queryShipList(Page<ShipmentForShipDTO> page) {
        if (page == null) {
            throw new BaseException("page参数不能为空");
        }
        Map<String, Object> condition = page.getCondition();
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        Object status = condition.get("status");
        //指令号，板车车牌号
        Object key = condition.get("key");
        if (status == null || StringUtils.isBlank(status.toString())) {
            throw new BaseException("状态信息不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        baseMapper.updateSQLMode();
        EntityWrapper<ShipmentForShipDTO> ew = new EntityWrapper<>();
        ew.eq("userCode", loginUser.getCode());
        ew.ne("releaseStatus", TableStatusEnum.STATUS_50.getCode());
        ew.eq("is_ship", TableStatusEnum.STATUS_1.getCode());
        //增加发车点
        if (StringUtils.isNotEmpty((String) key)) {
            ew.andNew().like("shipment_gid", key.toString()).or().like("plate_no", key.toString());
        }
        ew.orderBy("gmt_create", false)
                .orderBy("id", false)
                .orderBy("releaseId", false)
                .groupBy("shipment_gid");
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("status", status.toString());
        params.put("start", page.getOffsetCurrent());
        params.put("end", page.getSize());
        params.put("orderBy", "gmt_create desc,id desc");
        List<ShipmentForShipDTO> data = shipmentService.queryShipmentReleaseList(page, params, ew);
        ArrayList<String> gids = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(data)) {
            for (ShipmentForShipDTO dto : data) {
                gids.add(dto.getShipmentGid());
            }
            EntityWrapper<ShipmentForShipDTO> dataEW = new EntityWrapper<>();
            dataEW.in("shipment_gid", gids)
                    .eq("status", status.toString())
                    .ne("releaseStatus", TableStatusEnum.STATUS_50.getCode())
                    .eq("is_ship", TableStatusEnum.STATUS_1.getCode());
            if (StringUtils.isNotEmpty((String) key)) {
                dataEW.andNew().like("shipment_gid", key.toString()).or().like("plate_no", key.toString());
            }
            dataEW.orderBy("gmt_create", false)
                    .orderBy("id", false)
                    .orderBy("releaseId", false);
            List<ShipmentForShipDTO> list = shipmentService.queryShipmentReleases(dataEW);

            EntityWrapper<ShipmentForShipDTO> ttlEW = new EntityWrapper<>();
            ttlEW.eq("userCode", loginUser.getCode()).ne("releaseStatus", TableStatusEnum.STATUS_50.getCode())
                    .eq("is_ship", TableStatusEnum.STATUS_1.getCode());
            if (StringUtils.isNotEmpty((String) key)) {
                ttlEW.andNew().like("shipment_gid", key.toString()).or().like("plate_no", key.toString());
            }
            ttlEW.orderBy("gmt_create", false)
                    .orderBy("id", false)
                    .orderBy("releaseId", false);
            int total = shipmentService.countShipmentReleaseList(params, ttlEW);
            //调整未查询到数据后台不抛出异常
            if (CollectionUtils.isNotEmpty(list)) {
                for (ShipmentForShipDTO dto : list) {
                    List<OtmOrderRelease> releaseList = dto.getOtmOrderReleaseList();
                    if (CollectionUtils.isEmpty(releaseList)) {
                        continue;
                    }
                    dto.setShipCount(releaseList.size());
                    dto.setOriginLocationName(releaseList.get(0).getOriginLocationName());
                    dto.setDestLocationName(releaseList.get(0).getDestLocationName());
                    int count = 0;
                    for (OtmOrderRelease release : releaseList) {
                        //已交验后状态  算作已交验数据
                        if (TableStatusEnum.STATUS_WMS_HANDOVER.getCode().equals(release.getStatus())
                                || TableStatusEnum.STATUS_BS_DISPATCH.getCode().equals(release.getStatus())
                                || TableStatusEnum.STATUS_BS_ARRIVAL.getCode().equals(release.getStatus())
                                || TableStatusEnum.STATUS_BS_POD.getCode().equals(release.getStatus())
                                || TableStatusEnum.STATUS_OR_CLOSED.getCode().equals(release.getStatus())) {
                            count++;
                        }
                    }
                    dto.setHandoverCount(count);
                }
            }
            if(StringUtils.isNotEmpty((String)key)){
                page.setTotal(data.size());
            }else{
                page.setTotal(total);
            }
            page.setRecords(list);
        }
        return page;
    }


    /**
     * 装车发运 - 模糊搜索查询
     */
    @Override
    public Page<ShipmentRecordDTO> queryShipRecordList(Page<ShipmentRecordDTO> page) {
        //1、参数校验
        if (page == null) {
            throw new BaseException("page参数不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }
        //2、组装查询条件
        EntityWrapper<ShipmentRecordDTO> srdEw = new EntityWrapper<>();

        Map<String, Object> condition = page.getCondition();
        srdEw.eq("e.id", loginUser.getId());
        this.setShipRecordDtoParam(condition,srdEw,loginUser.getId());

        //3、结果查询
        List<ShipmentRecordDTO> list;
        if (condition != null && !condition.isEmpty() && TableStatusEnum.STATUS_Y.getCode().equals(condition.get("handleType"))) {
            //做导出用
            list = shipmentService.queryShipRecordList(srdEw);
        } else {
            list = shipmentService.queryShipRecordList(page, srdEw);
        }
        return page.setRecords(list);
    }

    @Override
    public void isRepeatShipment(List<String> tempList) {
        //1、查询是否已经确认发运
        for (String key : tempList) {
            Wrapper<OtmShipment> osEw = new EntityWrapper<>();
            osEw.eq("id", key);
            //osEw.eq("status", TableStatusEnum.STATUS_BS_DISPATCH.getCode());
            osEw.isNotNull("ship_date");
            List<OtmShipment> otmShipments = otmShipmentService.selectList(osEw);
            if (CollectionUtils.isNotEmpty(otmShipments)) {
                OtmShipment otmShipment = otmShipments.get(0);
                Wrapper<OtmOrderRelease> oorParams = new EntityWrapper<>();
                oorParams.eq("shipment_gid", otmShipment.getShipmentGid());
                List<OtmOrderRelease> otmOrderReleases = otmOrderReleaseService.selectList(oorParams);
                if (CollectionUtils.isNotEmpty(otmOrderReleases)) {
                    String msg = otmOrderReleases.get(0).getVin();
                    throw new BaseException("该发运记录的状态为【已发运】,车架号【" + msg + "】请勿重复发运");
                }
                throw new BaseException("该发运记录的状态为【已发运】，请勿重复发运");
            }
        }
    }

    /**
     * 装车发运 -- 点击/扫码获取详情
     */
    @Override
    public ShipmentForShipDTO getShipDetail(AppCommonQueryDTO dto) {
        if (dto == null) {
            throw new BaseException("dto 参数不能为空");
        }
        Map<String, String> condition = dto.getCondition();
        if (null == condition || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        String key = condition.get("key");
        if (StringUtils.isBlank(key)) {
            throw new BaseException("指令Id不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (null == loginUser) {
            throw new BaseException("请登录后进行该操作");
        }
        EntityWrapper<ShipmentForShipDTO> ew = new EntityWrapper<>();
        ew.ne("status", TableStatusEnum.STATUS_50.getCode())
                .eq("id", key)
                .eq("userCode", loginUser.getCode())
                .ne("releaseStatus", TableStatusEnum.STATUS_50.getCode())
                .eq("is_ship", TableStatusEnum.STATUS_1.getCode())
                .orderBy("gmt_create", false)
                .orderBy("id", false)
                .orderBy("releaseId", false);
        List<ShipmentForShipDTO> list = shipmentService.getShipDetail(ew);
        if (CollectionUtils.isEmpty(list)) {
            throw new BaseException("未查询到Id" + key + "的指令信息");
        }
        if (list.size() > 1) {
            throw new BaseException("查询到Id" + key + "多条指令信息");
        }

        for (ShipmentForShipDTO shipmentForShipDTO : list) {
            List<OtmOrderRelease> otmOrderReleases = shipmentForShipDTO.getOtmOrderReleaseList();
            if (CollectionUtils.isNotEmpty(otmOrderReleases)) {
                shipmentForShipDTO.setOriginLocationName(otmOrderReleases.get(0).getOriginLocationName());
                shipmentForShipDTO.setDestLocationName(otmOrderReleases.get(0).getDestLocationName());
            }
        }
        return list.get(0);
    }

    /**
     * 装车发运 -- 确认发运
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShipmentForShipDTO updateShip(AppCommonQueryDTO dto) {
        if (dto == null) {
            throw new BaseException("dto 参数不能为空");
        }
        Map<String, String> condition = dto.getCondition();
        if (null == condition || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        String key = condition.get("key");
        if (StringUtils.isBlank(key)) {
            throw new BaseException("指令Id不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (null == loginUser) {
            throw new BaseException("请登录后进行该操作");
        }
        //关联运单 起运地(多个发运地,需要多个发车点确认发运) ,key是指令id
        EntityWrapper<ShipmentForShipDTO> ew = new EntityWrapper<>();
        ew.ne("status", TableStatusEnum.STATUS_50.getCode())
                .eq("id", key)
                .eq("userCode", loginUser.getCode())
                .ne("releaseStatus", TableStatusEnum.STATUS_50.getCode())
                .isNull("ship_date")
                .eq("is_ship", TableStatusEnum.STATUS_1.getCode())
                .orderBy("gmt_create", false)
                .orderBy("id", false)
                .orderBy("releaseId", false);
        List<ShipmentForShipDTO> list = shipmentService.getShipDetail(ew);
        if (CollectionUtils.isEmpty(list)) {
            throw new BaseException("未查询到对应的指令信息");
        }
        if (list.size() > 1) {
            throw new BaseException("查询到多条指令信息");
        }

        ShipmentForShipDTO shipDTO = list.get(0);
        //减少请求,直接响应前端界面设置值
        shipDTO.setStatus(TableStatusEnum.STATUS_BS_DISPATCH.getCode());
        //更新运单明细 状态为已发运
        List<OtmOrderRelease> releaseList = shipDTO.getOtmOrderReleaseList();
        ArrayList<StatusLog> insertLogs = Lists.newArrayList();
        for (OtmOrderRelease oor : releaseList) {
            Wrapper<ExceptionRegister> registerWrapper = new EntityWrapper<>();
            registerWrapper.eq("vin", oor.getVin())
                    .eq("otm_status", TableStatusEnum.STATUS_N.getCode());
            ExceptionRegister exceptionRegister = exceptionRegisterService.selectOne(registerWrapper);
            if (Objects.nonNull(exceptionRegister)) {
                throw new BaseException("车架号:" + oor.getVin() + "异常不发运,请联系调度!");
            }

            //更新运单明otm_order_release细状态
            this.updateReleaseStatus(oor.getId(), null, loginUser.getName());
            oor.setStatus(TableStatusEnum.STATUS_BS_DISPATCH.getCode());

            //发运日志
            StatusLog sl = this.setStatusLog(loginUser.getName(),oor.getId(),TableStatusEnum.CHANNEL_APP.getCode());
            insertLogs.add(sl);

            //发运  更新车辆为已出库
            ArrayList<String> status = Lists.newArrayList();
            status.add(TableStatusEnum.STATUS_10.getCode());
            status.add(TableStatusEnum.STATUS_20.getCode());
            EntityWrapper<OutboundNoticeLine> nlEW = new EntityWrapper<>();
            nlEW.eq("line_source_key", oor.getReleaseGid())
                    .in("status", status)
                    .orderBy("id", false);
            OutboundNoticeLine noticeLine = outboundNoticeLineService.selectOne(nlEW);
            if (noticeLine != null) {
                //调用方法出库
                outboundShipLineService.shipByNoticeLineId(noticeLine.getId(), PutAwayType.NOTICE_PUTAWAY, SourceSystem.AUTO);
                //调用方法修改备料状态
                prepareHeaderService.updatePrepareFinishByLineId(noticeLine.getId(), loginUser.getName());
            }

            //推送OTM/BMS
            integrationService.toOtmBms(shipDTO, oor,null,loginUser.getName());
        }
        //调整头发运状态 增加判断明细都为已发运
        String shipmentGid = shipDTO.getShipmentGid();
        ArrayList<String> neStatus = Lists.newArrayList(TableStatusEnum.STATUS_50.getCode(),
                TableStatusEnum.STATUS_BS_ARRIVAL.getCode(),
                TableStatusEnum.STATUS_BS_DISPATCH.getCode());
        EntityWrapper<OtmOrderRelease> oorEW = new EntityWrapper<>();
        oorEW.eq("shipment_gid", shipmentGid);
                //.notIn("status", neStatus);
        oorEW.isNull("ship_date");
        oorEW.ne("status", TableStatusEnum.STATUS_50.getCode());
        int notShipCount = otmOrderReleaseService.selectCount(oorEW);
        //获取指令状态
        String status = shipDTO.getStatus();
        //如果指令状态为已入库，则返回false，不进下面if执行指令状态修改为已发运的操作
        Boolean result = updateShipStatus(status);
        if (notShipCount == 0 && result){
            this.modifyShipmentStatus(shipDTO.getId(),TableStatusEnum.STATUS_BS_DISPATCH.getCode(),TableStatusEnum.CHANNEL_APP.getCode(),null);
        }
        //statusLog 操作日志记录
        if (CollectionUtils.isNotEmpty(insertLogs)) {
            LOGGER.info("记录发运数据至status_log开始。。。。。。。。。。。");
            statusLogService.insertBatch(insertLogs);
            LOGGER.info("记录发运数据至status_log结束。。。。。。。。。。。");
        }
        return shipDTO;
    }



    private ReleaseWithShipmentDTO getDetailScan(String key, User loginUser) {
        EntityWrapper<ReleaseWithShipmentDTO> ew = new EntityWrapper<>();
        ew.isNotNull("userId")
                .eq("is_ship", TableStatusEnum.STATUS_1.getCode())
                .ne("status", TableStatusEnum.STATUS_50.getCode())
                .eq("userCode", loginUser.getCode())
                .andNew()
                .eq("qr_code", key)
                .or()
                .eq("vin", key)
                .or()
                .eq("cus_order_no", key)
                .orderBy("gmt_create", false)
                .orderBy("id", false);
        List<ReleaseWithShipmentDTO> data = baseMapper.getReleaseShipDetail(ew);
        if (CollectionUtils.isEmpty(data)) {
            throw new BaseException("为查询到对应发运数据");
        }
        if (data.size() > 1) {
            throw new BaseException("查询到key:" + key + "多条信息");
        }
        return data.get(0);
    }

    private ReleaseWithShipmentDTO getDetailClick(String key, User loginUser) {
        EntityWrapper<ReleaseWithShipmentDTO> ew = new EntityWrapper<>();
        ew.isNotNull("userId")
                .eq("is_ship", TableStatusEnum.STATUS_1.getCode())
                .ne("status", TableStatusEnum.STATUS_50.getCode())
                .eq("userCode", loginUser.getCode())
                .eq("id", key)
                .orderBy("gmt_create", false)
                .orderBy("id", false);
        List<ReleaseWithShipmentDTO> data = baseMapper.getReleaseShipDetail(ew);
        if (CollectionUtils.isEmpty(data)) {
            throw new BaseException("为查询到对应发运数据");
        }
        if (data.size() > 1) {
            throw new BaseException("查询到key:" + key + "多条信息");
        }
        return data.get(0);
    }

    @Override
    public void updateVin(AppCommonQueryDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        Map<String, String> condition = dto.getCondition();
        if (null == condition || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        if (!condition.containsKey("key") || StringUtils.isBlank(condition.get("key"))) {
            throw new BaseException("指令id不能为空");
        }
        if (!condition.containsKey("vin") || StringUtils.isBlank(condition.get("vin"))) {
            throw new BaseException("车架号不能为空");
        }

        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("未查询到登录用户");
        }
        if (StringUtils.isBlank(loginUser.getCode())) {
            throw new BaseException("用户编码不能为空");
        }
        OtmOrderRelease orderRelease = new OtmOrderRelease();
        orderRelease.setId(Long.valueOf(condition.get("key")));
        orderRelease.setVin(condition.get("vin"));
        baseMapper.updateById(orderRelease);
        OtmOrderRelease orderReleaseResult = baseMapper.selectById(orderRelease.getId());
        // 车架号回传OTM
        sendVinBindOTM(String.valueOf(orderReleaseResult.getId()), orderReleaseResult.getVin(), orderReleaseResult);
    }

    @Override
    public Page<VechielModelDTO> queryCarModelInfo(Page<VechielModelDTO> page) {
        //调用lisa-integration系统获取车型信息,通过httpclient的post方式调用
        String result = HttpClientUtil.postJson(properties.getIntegrationhost() + InterfaceAddrEnum.VEHICLE_URL.getAddress(), null, JSONObject.toJSONString(page), properties.getSocketTimeOut());
        if (StringUtils.isNotEmpty(result)) {
            RestfulResponse<Page<VechielModelDTO>> restfulResponse = JSON.parseObject(result,
                    new TypeReference<RestfulResponse<Page<VechielModelDTO>>>() {
                    });
            if (Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 0) {
                return restfulResponse.getData();
            }
        }
        return null;
    }

    @Override
    public void updateVehicleInfo (AppCommonQueryDTO conditions) {
        //1、修改车型信息参数判断
        Map<String, String> condition = this.setUpdateVehicleInfoParams(conditions);

        //2、登录校验
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("未查询到登录用户");
        }
        if (StringUtils.isBlank(loginUser.getCode())) {
            throw new BaseException("用户编码不能为空");
        }

        //3、查询是否改装过车型，如果改装过，不需要再次修改
        OtmOrderRelease release = baseMapper.selectById(Long.valueOf(condition.get("key")));
        if(null != release){
            if(StringUtils.isNotEmpty(release.getModifiedVehicleType()) && TableStatusEnum.STATUS_Y.getCode().equals(release.getIsModVehicle())){
                throw new BaseException("该车已经改装过车型，无需再次更改！");
            }
        }

        //4、修改车型
        OtmOrderRelease otmOrderRelease = new OtmOrderRelease();
        otmOrderRelease.setIsModVehicle("Y");
        otmOrderRelease.setId(Long.valueOf(condition.get("key")));
        otmOrderRelease.setModifiedVehicleType(condition.get("modifiedVehicleType"));
        otmOrderRelease.setModifiedVehicleUser(loginUser.getName());
        otmOrderRelease.setModifiedVehicleTime(new Date());
        baseMapper.updateById(otmOrderRelease);

        //5、同步OTM
        boolean syncOTMFlag = this.vehicleToOTM(otmOrderRelease.getId(), condition.get("modifiedVehicleCode"));
        if (StringUtils.isEmpty(condition.get("modifiedVehicleCode"))) {
            throw new BaseException("修改车型的code为空，请重新确认!");
        }
        LOGGER.info("修改车型同步OTM返回结果syncOTMFlag{} ", syncOTMFlag);
    }

    /**
     * 车型同步OTM
     *
     * @param id
     */
    private boolean vehicleToOTM(Long id, String modifiedVehicleCode) {
        OtmOrderRelease orderReleaseResult = baseMapper.selectById(id);
        Map<String, String> param = new HashMap<>();
        //客户 可不传
        param.put("customer", "");
        //OMS订单号 必传
        param.put("orderReleaseXid", orderReleaseResult.getReleaseGid());
        //车架号 必传
        param.put("vin", orderReleaseResult.getVin());
        //改装后车型 必传
        param.put("stdVechile", modifiedVehicleCode);
        param.put("shipmentGid", orderReleaseResult.getShipmentGid());
        String result = HttpClientUtil.postJson(properties.getIntegrationhost() + InterfaceAddrEnum.VEHICLE_SYNS_TOOTM_URL.getAddress(), null, JSONObject.toJSONString(param), properties.getSocketTimeOut());
        if (StringUtils.isNotEmpty(result)) {
            RestfulResponse<Map<String, Object>> restfulResponse = JSON.parseObject(result, new TypeReference<RestfulResponse<Map<String, Object>>>() {
            });
            if (Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 0) {
                return true;
            }
        }
        return false;
    }

    private Map<String, String> setUpdateVehicleInfoParams(AppCommonQueryDTO conditions) {
        Map<String, String> condition = conditions.getCondition();
        if (Objects.isNull(condition)) {
            throw new BaseException( "入参不能为空");
        }
        String keyId = condition.get("key");
        if (StringUtils.isEmpty(keyId)) {
            throw new BaseException("主键id不能为空");
        }
        String vehicleType = condition.get("modifiedVehicleType");
        if (StringUtils.isEmpty(vehicleType)) {
            throw new BaseException( "车型不能为空");
        }
        return condition;
    }


    private void sendVinBindOTM(String id, String vin, OtmOrderRelease orderReleaseResult) {
        new Thread(() -> {
            OTMEvent event = integrationService.getOtmEvent(
                    id,
                    orderReleaseResult.getReleaseGid(),
                    InterfaceEventEnum.BINDING_CODE.getCode(),
                    orderReleaseResult.getShipmentGid(),
                    "绑定车架号信息回传OTM");
            event.setVin(vin);
            String res = nodeExport.exportEventToOTM(event);
            if (StringUtils.isNotBlank(res)) {
                integrationService.insertExportLog(
                        id,
                        event,
                        res,
                        "绑定车架号信息回传OTM",
                        InterfaceEventEnum.BINDING_CODE.getCode());
            }
        }).start();
    }


    @Override
    public List<String> releaseDespatch  (Map<String, String> param)  {
        //1、判断入参是否为空，入参为运单表的id，多个运单发运以英文逗号“,”分开
        String releaseIds = param.get("key");
        if(StringUtils.isEmpty(releaseIds)){
            throw new BaseException("运单ID【releaseIds】为空，请重新确认！");
        }

        //2、登录状态校验
        User loginUser = userService.getLoginUser();
        if (null == loginUser) {
            throw new BaseException("请登录后进行该操作");
        }

        //3.发运时间不能超过当前时间24小时
        String despatchTime = param.get("shipTime");
        releaseDespatchTime(despatchTime);

        //3、根据运单id查询运单信息
        List<OtmReleaseForShipDTO> releaseList = this.queryOtmReleaseList(releaseIds,loginUser.getCode());

        //4、更新运单信息 状态为已发运
        ArrayList<String> resultList = this.modifiedReleaseStatus(releaseList,loginUser,param.get("shipTime"));
        return resultList;
    }

    //判断发运时间不能超过当前时间24小时,参数为前台输入的发运时间
    public Boolean releaseDespatchTime(String despatchTime){
        //输入的发运时间不能为空
        if(StringUtils.isBlank(despatchTime)){
            throw new BaseException("发运时间不能为空");
        }
        //当前系统时间
        Date date = new Date();
        //实际发运时间
        DateTime shipTime = DateUtil.parse(despatchTime);
            Long lastTime = shipTime.getTime()-date.getTime();
            if(!( lastTime<(24*3600000))){
                throw new BaseException("发运时间不能超过当前时间24小时");
            }
            return true;
    }


    @Override
    public Page<ShipmentRecordDTO> queryNewChannelReleaseList (Page<ShipmentRecordDTO> page) {
        //1、参数校验
        if(null == page){
            throw new BaseException("参数【page】不能为空！");
        }

        //2、登录用户校验
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }

        //3、筛选条件组装
        EntityWrapper<ShipmentRecordDTO> ew = this.setShipParamDtoParam(page,loginUser);

        //4、数据查询并返回
        List<ShipmentRecordDTO> list = shipmentService.queryNewChannelReleaseList(page, ew);

        return page.setRecords(list);
    }

    @Override
    public void despatchNewChannel (Map<String, String> param) {
        //1、判断入参是否为空，入参为运单表的id，多个运单发运以英文逗号“,”分开
        String releaseIds = param.get("key");
        if(StringUtils.isEmpty(releaseIds)){
            throw new BaseException("运单ID【key】为空，请重新确认！");
        }

        //2、登录状态校验
        User loginUser = userService.getLoginUser();
        LOGGER.info("despatchNewChannel 新渠道订单单车发运登录用户信息{}",loginUser.toString());
        if (null == loginUser) {
            throw new BaseException("请登录后进行该操作");
        }

        //3、根据运单id查询运单信息
        List<OtmReleaseForShipDTO> releaseList = this.queryNewChannelRelease(releaseIds);
        LOGGER.info("根据运单id查询运单列表信息结果：{}",releaseList);

        //4、更新运单信息 状态为已发运
        ArrayList<StatusLog> statusLogs = this.updateNewChannelReleaseStatus(releaseList,loginUser);
        LOGGER.info("更新运单信息存入status_log表的日志信息：{}",statusLogs);

        //5、statusLog 操作日志记录
        if (CollectionUtils.isNotEmpty(statusLogs)) {
            statusLogService.insertBatch(statusLogs);
        }
    }

    @Override
    public void cancleShipment (String shipmentGid, String cancleShipUser) {
        if (StringUtils.isEmpty(shipmentGid)) {
            throw new BaseException("取消指令参数不能为空");
        }
        if(StringUtils.isEmpty(cancleShipUser)){
            cancleShipUser = "OTM取消发运";
        }
        //1、查询指令ship_date（发运时间）不为空，状态不为50，备注不为“指令删除”的数据是否存在
        EntityWrapper<OtmCancleShipment> releaseEw = new EntityWrapper<>();
        List<String> statusList = new ArrayList<>();
        statusList.add(TableStatusEnum.STATUS_50.getCode());
        statusList.add(TableStatusEnum.STATUS_BS_CREATED.getCode());
        statusList.add(TableStatusEnum.STATUS_BS_INBOUND.getCode());
        String[] otmShipmentGids = shipmentGid.split(",");
        releaseEw.isNotNull("oor.ship_date");
        releaseEw.in("oor.shipment_gid", Arrays.asList(otmShipmentGids));
        releaseEw.notIn("oor.status", statusList);
        List<OtmCancleShipment> wmsOrderReleases = baseMapper.queryCancleShipment(releaseEw);
        if (CollectionUtils.isEmpty(wmsOrderReleases)) {
            throw new BaseException("指令查询结果为空或指令状态不可取消发运！");
        }
        if (otmShipmentGids.length != wmsOrderReleases.size()) {
            String compareResult = this.compareWmsNoShipment(otmShipmentGids, wmsOrderReleases);
            if (StringUtils.isNotEmpty(compareResult)) {
                throw new BaseException("指令号不存在或者状态不可取消发运" + compareResult);
            }
        }

        for (OtmCancleShipment otmCancleShipment : wmsOrderReleases) {
            if (StringUtils.isNotEmpty(otmCancleShipment.getInboundStatus()) && TableStatusEnum.STATUS_30.getCode().equals(otmCancleShipment.getInboundStatus())) {
                //修改运单状态
                this.cancleReleaseStatus(TableStatusEnum.STATUS_BS_INBOUND.getCode(), otmCancleShipment.getId());
            } else {
                this.cancleReleaseStatus(TableStatusEnum.STATUS_BS_CREATED.getCode(), otmCancleShipment.getId());
            }
            //修改指令状态
            this.cancleShipmentStatus(otmCancleShipment.getShipmentGid());

            pushCancleDispatchTOtms(otmCancleShipment.getShipmentGid(),otmCancleShipment.getReleaseGid(),cancleShipUser,otmCancleShipment.getId(),
                    otmCancleShipment.getVin());
        }

        //新增取消记录数据
        EntityWrapper<OtmShipment> otmShipmentEw = new EntityWrapper<>();
        otmShipmentEw.ne("status", TableStatusEnum.STATUS_50.getCode());
        otmShipmentEw.in("shipment_gid", Arrays.asList(otmShipmentGids));
        List<OtmShipment> otmShipments = otmShipmentService.selectList(otmShipmentEw);
        if (CollectionUtils.isNotEmpty(otmShipments)) {
            for (OtmShipment otmShipment : otmShipments) {
                StatusLog statusLog = new StatusLog();
                statusLog.setTableId(String.valueOf(otmShipment.getId()));
                statusLog.setChannelType("OTM");
                statusLog.setUserCreate(cancleShipUser);
                statusLog.setStatusName("OTM取消发运");
                statusLog.setTableType(TableStatusEnum.STATUS_0.getCode());
                statusLog.setStatus(TableStatusEnum.STATUS_CANCLE_DISPATCH.getCode());
                statusLogService.insert(statusLog);
            }
        }

        //TODO 记录处理取消发运到日志系统
    }

    /**
     * 取消发运推送tms
     *
     * @param shipmentGid 指令号
     * @param releaseGid  运单号
     * @param shipUser    otm取消发运操作人
     * @param releaseId   运单id
     * @param vin         车架号
     */
    private void pushCancleDispatchTOtms (String shipmentGid, String releaseGid, String shipUser, long releaseId, String vin) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("vin", vin);
            param.put("shipUser", shipUser);
            param.put("cancleDate", new Date());
            param.put("releaseGid", releaseGid);
            param.put("shipmentGid", shipmentGid);
            String paramJSON = JSONObject.toJSONString(param);
            ItfExplogLine itfExplogLine = new ItfExplogLine();
            String resJson = HttpClientUtil.postJson(properties.getCancleShipDataForBMS(), null, paramJSON, 60000);
            LOGGER.info("数据推送结果为：resJson{}", resJson);
            if (StringUtils.isNotEmpty(resJson)) {
                RestfulResponse<String> restfulResponse = JSON.parseObject(resJson, new TypeReference<RestfulResponse<String>>() {
                });
                if (Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 0) {
                    itfExplogLine.setRequestId(restfulResponse.getData());
                } else {
                    itfExplogLine.setExportRemarks(restfulResponse.getMessage());
                }
            }
            //日志到WiF
            itfExplogLine.setId(flakeId.nextId());
            itfExplogLine.setDataContent(paramJSON);
            itfExplogLine.setExportRemarks("OTM取消发运");
            itfExplogLine.setUserCreate(shipUser);
            itfExplogLine.setRelationId(releaseId);
            itfExplogLine.setGmtCreate(new Date());
            itfExplogLine.setInterfaceUrl(properties.getCancleShipDataForBMS());
            itfExplogLine.setExportStatus(TableStatusEnum.STATUS_1.getCode());
            itfExplogLine.setExportType(TableStatusEnum.STATUS_CANCLE_DISPATCH.getCode());
            itfExplogLine.setTargetSource("TMS");
            itfExplogLineMapper.insert(itfExplogLine);
        } catch (Exception e) {
            LOGGER.error("推送TMS系统异常{}", e.getMessage());
        }
    }

    @Override
    public void updateReleaseInfo (ReleaseDTO releaseDTO) {
        if (null == releaseDTO) {
            throw new BaseException("更改信息入参为空！");
        }
        //1、更新运单信息（先判断是否在存在运单信息）
        EntityWrapper<OtmOrderRelease> ew = new EntityWrapper<>();
        ew.ne("status", TableStatusEnum.STATUS_50.getCode());
        ew.eq("shipment_gid", releaseDTO.getShipmentGid());
        ew.eq("release_gid", releaseDTO.getReleaseGid());
        List<OtmOrderRelease> releaseList = baseMapper.selectList(ew);
        if (CollectionUtils.isEmpty(releaseList)) {
            throw new BaseException("系统运单号" + releaseDTO.getReleaseGid() + "不存在");
        }
        OtmOrderRelease otmOrderRelease = releaseList.get(0);
        try {
            //更新相关信息
            if (StringUtils.isNotEmpty(releaseDTO.getVin()) && !releaseDTO.getVin().equals(otmOrderRelease.getVin())) {
                //2、如果更新了车架号，出入库通知单，库存信息均需更改
                updateInOutBoundSku(releaseDTO, otmOrderRelease);
            } else {
                updateVinInfo(releaseDTO,otmOrderRelease.getId());
            }
        } catch (Exception e) {
            throw new BaseException(releaseDTO.getReleaseGid() + "系统异常");
        }
    }

    @Override
    public void updateRelease (OtmOrderRelease otmOrderRelease) {
        baseMapper.updateRelease(otmOrderRelease);
    }

    @Override
    public void pushInboundDispatch (OtmOrderRelease otmOrderRelease, OtmShipment otmShipmentRes, String shipDate) {
        //设置回传信息给OTM/BMS的参数
        ShipmentForShipDTO shipmentForShipDTO = new ShipmentForShipDTO();
        shipmentForShipDTO.setDriverGid(otmShipmentRes.getDriverGid());
        shipmentForShipDTO.setServiceProviderGid(otmShipmentRes.getServiceProviderGid());
        shipmentForShipDTO.setPlateNo(otmShipmentRes.getPlateNo());
        shipmentForShipDTO.setTrailerNo(otmShipmentRes.getTrailerNo());
        //回传信息给OTM/BMS
        integrationService.toOtmBms(shipmentForShipDTO, otmOrderRelease, shipDate, "入库自动发运");
    }

    /**
     * 更新出入库
     * 更新库存
     */
    private void updateInOutBoundSku (ReleaseDTO releaseDTO, OtmOrderRelease otmOrderRelease) {
        //修改车型信息
        updateVinInfo(releaseDTO, otmOrderRelease.getId());

        //修改出库通知单
        updateOutboundInfo(otmOrderRelease.getShipmentGid(), otmOrderRelease.getReleaseGid(), releaseDTO.getVin(), otmOrderRelease.getVin(),
                releaseDTO.getCusVehicleType());

        //修改入库通知单
        updateInboundInfo(otmOrderRelease.getShipmentGid(), otmOrderRelease.getReleaseGid(), releaseDTO.getVin(), otmOrderRelease.getVin(), releaseDTO.getCusVehicleType());

    }

    /**
     * 修改入库通知单的车架号信息
     *
     * @param shipmentGid    指令号
     * @param releaseGid     运单号
     * @param otmVin         车架号
     * @param wmsVin         车架号
     * @param cusVehicleType 客户车型
     */
    private void updateInboundInfo (String shipmentGid, String releaseGid, String otmVin, String wmsVin, String cusVehicleType) {
        long putWayLocationId = 0;
        //查询入库通知单头表
        EntityWrapper<InboundNoticeHeader> inHeaderEw = new EntityWrapper<>();
        inHeaderEw.eq("source_key", shipmentGid);
        inHeaderEw.ne("status", TableStatusEnum.STATUS_50.getCode());
        List<InboundNoticeHeader> inboundNoticeHeaders = inboundNoticeHeaderMapper.selectList(inHeaderEw);
        //查询是否有入库通知单头表数据
        if (CollectionUtils.isNotEmpty(inboundNoticeHeaders)) {
            InboundNoticeHeader inboundNoticeHeader = inboundNoticeHeaders.get(0);
            EntityWrapper<InboundNoticeLine> inLineEw = new EntityWrapper<>();
            inLineEw.eq("header_id", inboundNoticeHeader.getId());
            inLineEw.eq("line_source_key", releaseGid);
            inLineEw.ne("status", TableStatusEnum.STATUS_50.getCode());
            List<InboundNoticeLine> inboundNoticeLines = inboundNoticeLineMapper.selectList(inLineEw);
            //查询是否有入库通知单明细信息
            if (CollectionUtils.isNotEmpty(inboundNoticeLines)){
                InboundNoticeLine inlineParam = new InboundNoticeLine();
                inlineParam.setLotNo1(otmVin);
                inlineParam.setId(inboundNoticeLines.get(0).getId());
                inboundNoticeLineMapper.updateById(inlineParam);

                //更新入库记录明细信息
                EntityWrapper<InboundPutawayLine> inboundPutWayEw = new EntityWrapper<>();
                inboundPutWayEw.eq("notice_line_id", inboundNoticeLines.get(0).getId());
                inboundPutWayEw.eq("lot_no1", wmsVin);
                List<InboundPutawayLine> putawayLines = inboundPutawayLineMapper.selectList(inboundPutWayEw);
                if (CollectionUtils.isNotEmpty(putawayLines)) {
                    putWayLocationId = putawayLines.get(0).getLocationId();
                    InboundPutawayLine inboundPutawayLine = new InboundPutawayLine();
                    inboundPutawayLine.setLotNo1(otmVin);
                    inboundPutawayLineMapper.update(inboundPutawayLine, inboundPutWayEw);
                }
            }
            //修改库存
            iSkuService.updateSkuInfo(otmVin, wmsVin, inboundNoticeHeader.getStoreHouseId(), cusVehicleType,putWayLocationId);
        }
    }

    /**
     * 修改出库通知单车架号信息
     *
     * @param shipmentGid    指令号
     * @param releaseGid     运单号
     * @param otmVin         otm车架号
     * @param wmsVin         wms车架号
     * @param cusVehicleType otm客户车型
     */
    private void updateOutboundInfo (String shipmentGid, String releaseGid, String otmVin, String wmsVin, String cusVehicleType) {
        //查询是否有出库通知单头
        long shipLineLocationId = 0;
        EntityWrapper<OutboundNoticeHeader> outHeaderEw = new EntityWrapper<>();
        outHeaderEw.eq("source_key", shipmentGid);
        outHeaderEw.ne("status", TableStatusEnum.STATUS_50.getCode());
        List<OutboundNoticeHeader> outboundNoticeHeaders = outboundNoticeHeaderMapper.selectList(outHeaderEw);
        if (CollectionUtils.isNotEmpty(outboundNoticeHeaders)) {
            OutboundNoticeHeader outboundNoticeHeader = outboundNoticeHeaders.get(0);
            EntityWrapper<OutboundNoticeLine> outLineEwp = new EntityWrapper<>();
            outLineEwp.eq("header_id", outboundNoticeHeader.getId());
            outLineEwp.eq("line_source_key", releaseGid);
            outLineEwp.ne("status", TableStatusEnum.STATUS_50.getCode());
            List<OutboundNoticeLine> outboundNoticeLines = outboundNoticeLineService.selectList(outLineEwp);
            //是否有出库通知单明细信息
            if (CollectionUtils.isNotEmpty(outboundNoticeLines)) {
                OutboundNoticeLine outlineParam = new OutboundNoticeLine();
                outlineParam.setLotNo1(otmVin);
                outlineParam.setId(outboundNoticeLines.get(0).getId());
                outboundNoticeLineService.updateById(outlineParam);

                //查询出库记录
                EntityWrapper<OutboundShipLine> outShipHeaderEw = new EntityWrapper<>();
                outShipHeaderEw.eq("notice_line_id", outboundNoticeLines.get(0).getId());
                outShipHeaderEw.eq("lot_no1", wmsVin);
                List<OutboundShipLine> outshipLines = outboundShipLineService.selectList(outShipHeaderEw);
                if (CollectionUtils.isNotEmpty(outshipLines)) {
                    shipLineLocationId = outshipLines.get(0).getLocationId();
                    //更改出库记录表数据
                    OutboundShipLine outboundShipLine = new OutboundShipLine();
                    outboundShipLine.setLotNo1(otmVin);
                    outboundShipLineService.update(outboundShipLine, outShipHeaderEw);
                }
            }
            //修改库存信息
            iSkuService.updateSkuInfo(otmVin, wmsVin, outboundNoticeHeader.getStoreHouseId(), cusVehicleType,shipLineLocationId);
        }
    }

    /**
     * 更新运单相关信息
     *
     * @param releaseDTO
     * @param releaseId
     */
    private void updateVinInfo (ReleaseDTO releaseDTO, Long releaseId) {
        baseMapper.updateReleaseInfo(releaseDTO);
        try {
            //修改车架号需要修改itf日志数据
            if (StringUtils.isNotEmpty(releaseDTO.getVin())) {
                OtmOrderRelease release = otmOrderReleaseService.selectById(releaseId);
                if (null != release && null != release.getShipDate()) {
                    EntityWrapper<ItfExplogLine> itfEw = new EntityWrapper<>();
                    itfEw.eq("relation_id", releaseId);
                    itfEw.eq("export_type", InterfaceEventEnum.BS_OP_DELIVERY.getCode());
                    List<ItfExplogLine> itfExplogLines = itfExplogLineMapper.selectList(itfEw);
                    for (ItfExplogLine wif : itfExplogLines) {
                        JSONObject jsonObject = JSON.parseObject(wif.getDataContent());
                        jsonObject.put("vin", releaseDTO.getVin());
                        ItfExplogLine param = new ItfExplogLine();
                        param.setDataContent(jsonObject.toString());
                        param.setId(wif.getId());
                        itfExplogLineMapper.updateById(param);
                    }
                }
            }

            //如果运单信息更新，出入库数据也需要同步
            if (StringUtils.isNotEmpty(releaseDTO.getCusOrderNo())) {
                EntityWrapper<InboundNoticeHeader> inHeaderEw = new EntityWrapper<>();
                inHeaderEw.eq("source_key", releaseDTO.getShipmentGid());
                inHeaderEw.ne("status", TableStatusEnum.STATUS_50.getCode());
                List<InboundNoticeHeader> inboundNoticeHeaders = inboundNoticeHeaderMapper.selectList(inHeaderEw);
                if (CollectionUtils.isNotEmpty(inboundNoticeHeaders)) {
                    EntityWrapper<InboundNoticeLine> inboundEw = new EntityWrapper<>();
                    inboundEw.eq("line_source_key", releaseDTO.getReleaseGid());
                    inboundEw.eq("header_id", inboundNoticeHeaders.get(0).getId());
                    inboundEw.ne("status", TableStatusEnum.STATUS_50.getCode());
                    List<InboundNoticeLine> inboundNoticeLines = inboundNoticeLineMapper.selectList(inboundEw);
                    if(CollectionUtils.isNotEmpty(inboundNoticeLines)){
                        if(!releaseDTO.getCusOrderNo().equals(inboundNoticeLines.get(0).getOwnerOrderNo())){
                            InboundNoticeLine inboundNoticeLine = new InboundNoticeLine();
                            inboundNoticeLine.setOwnerOrderNo(releaseDTO.getCusOrderNo());
                            inboundNoticeLineMapper.update(inboundNoticeLine, inboundEw);
                        }
                    }
                }

                EntityWrapper<OutboundNoticeHeader> outHeaderEw = new EntityWrapper<>();
                outHeaderEw.eq("source_key", releaseDTO.getShipmentGid());
                outHeaderEw.ne("status", TableStatusEnum.STATUS_50.getCode());
                List<OutboundNoticeHeader> outboundNoticeHeaders = outboundNoticeHeaderMapper.selectList(outHeaderEw);
                if (CollectionUtils.isNotEmpty(outboundNoticeHeaders)) {
                    EntityWrapper<OutboundNoticeLine> outboundEw = new EntityWrapper<>();
                    outboundEw.eq("line_source_key", releaseDTO.getReleaseGid());
                    outboundEw.eq("header_id", outboundNoticeHeaders.get(0).getId());
                    outboundEw.ne("status", TableStatusEnum.STATUS_50.getCode());
                    List<OutboundNoticeLine> outboundNoticeLines = outboundNoticeLineService.selectList(outboundEw);
                    if(CollectionUtils.isNotEmpty(outboundNoticeLines)){
                        if(!releaseDTO.getCusOrderNo().equals(outboundNoticeLines.get(0).getOwnerOrderNo())){
                            OutboundNoticeLine outboundNoticeLine = new OutboundNoticeLine();
                            outboundNoticeLine.setOwnerOrderNo(releaseDTO.getCusOrderNo());
                            outboundNoticeLineService.update(outboundNoticeLine, outboundEw);
                        }
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("修改运单信息更改json异常{}", e.getMessage());
        }
    }

    /**
     * OTM取消指令，修改指令状态
     *
     * @param shipmentGid 指令号
     */
    private void cancleShipmentStatus (String shipmentGid) {
        EntityWrapper<OtmShipment> shipmentEw = new EntityWrapper<>();
        shipmentEw.eq("shipment_gid", shipmentGid);
        shipmentEw.ne("status", TableStatusEnum.STATUS_50.getCode());
        OtmShipment otmShipment = new OtmShipment();
        otmShipment.setStatus(TableStatusEnum.STATUS_BS_CREATED.getCode());
        otmShipmentMapper.update(otmShipment, shipmentEw);
    }

    /**
     * otm取消运单发运
     * @param id
     */
    private void cancleReleaseStatus (String releaseStatus, long id) {
        baseMapper.cancleReleaseStatus(releaseStatus,id);

    }

    /**
     * otm传递的数据和wms查询结果对比，把没有下发过来的指令提示给otm
     * @param otmShipmentGids otm下发的指令
     * @param wmsOrderReleases wms查询结果的指令
     */
    private String compareWmsNoShipment (String[] otmShipmentGids, List<OtmCancleShipment> wmsOrderReleases) {
        List<String> wmsShipmentList = new ArrayList<>();
        for(OtmCancleShipment otmOrderRelease:wmsOrderReleases){
            wmsShipmentList.add(otmOrderRelease.getShipmentGid());
        }
        StringBuffer sb = new StringBuffer();

        for(String shipmentId:otmShipmentGids){
            if(!wmsShipmentList.contains(shipmentId)){
                sb.append(shipmentId).append(",");
            }
        }
        return sb.toString();
    }

    /***
     * 修改运单状态
     * @param releaseList 运单信息
     * @param loginUser 登录用户
     * @return 日志信息
     */
    private ArrayList<StatusLog> updateNewChannelReleaseStatus (List<OtmReleaseForShipDTO> releaseList, User loginUser) {
        ArrayList<StatusLog> insertLogs = Lists.newArrayList();
        for (OtmReleaseForShipDTO oor : releaseList) {
            //1、是否标记为异常发运,标记为异常发运的车架号不能发运
            this.isExceptionDespatch(oor.getVin());

            //2、是否为已发运
            this.isShip(oor);

            //3、更新运单状态
            this.updateReleaseStatus(oor.getId(), null, loginUser.getName());
            oor.setStatus(TableStatusEnum.STATUS_BS_DISPATCH.getCode());

            //4、新增状态日志表
            StatusLog sl = this.setStatusLog(loginUser.getName(), oor.getId(), TableStatusEnum.CHANNEL_PC.getCode());
            insertLogs.add(sl);

            //6、修改指令状态，并把已发运的数据同步到BMS/OTM
            this.passBackBMSAndOTM(oor,null, loginUser.getName());
        }
        return insertLogs;
    }

    /**
     * 查询发运订单
     *
     * @param releaseIds 运单id
     * @return 可发运的运单信息
     */
    private List<OtmReleaseForShipDTO> queryNewChannelRelease (String releaseIds) {
        //关联运单 启运地(多个发运地,需要多个发车点确认发运)
        EntityWrapper<OtmReleaseForShipDTO> ew = new EntityWrapper<>();
        ew.in("releaseId", releaseIds.split(","));
        ew.ne("releaseStatus", TableStatusEnum.STATUS_50.getCode());
        ew.eq("order_att","新渠道订单");
        ew.orderBy("re_gmt_modify", false);
        ew.orderBy("releaseId", false);
        List<OtmReleaseForShipDTO> list = otmShipmentMapper.queryChannelOtmReleaseList(ew);
        if (CollectionUtils.isEmpty(list)) {
            throw new BaseException("未查询到" + releaseIds + "对应的运单信息");
        }
        return list;
    }

    /**
     * 组装入参
     * @param page
     * @param loginUser
     * @return
     */
    private EntityWrapper<ShipmentRecordDTO> setShipParamDtoParam (Page<ShipmentRecordDTO> page, User loginUser) {
        EntityWrapper<ShipmentRecordDTO> srdEw = new EntityWrapper<>();
        Map<String, Object> condition = page.getCondition();
        srdEw.eq("b.order_att","新渠道订单");
        this.setShipRecordDtoParam(condition,srdEw, loginUser.getId());
        srdEw.orderBy("b.gmt_modified", false);
        return srdEw;
    }

    /**
     * 组装筛选条件
     * @param condition
     * @param srdEw
     * @param loginId
     */
    private void setShipRecordDtoParam (Map<String, Object> condition, EntityWrapper<ShipmentRecordDTO> srdEw, Integer loginId) {
        if (condition != null && !condition.isEmpty()) {
            if (Objects.nonNull(condition.get("cusWaybillNo")) && StringUtils.isNotEmpty((String) condition.get("cusWaybillNo"))) {
                srdEw.eq("b.cus_waybill_no", condition.get("cusWaybillNo"));
            }
            if (Objects.nonNull(condition.get("cusOrderNo")) && StringUtils.isNotEmpty((String) condition.get("cusOrderNo"))) {
                srdEw.like("b.cus_order_no", condition.get("cusOrderNo").toString());
            }
            if (Objects.nonNull(condition.get("serviceProviderName")) && StringUtils.isNotEmpty((String) condition.get("serviceProviderName"))) {
                srdEw.like("a.service_provider_name", condition.get("serviceProviderName").toString());
            }
            if (Objects.nonNull(condition.get("isUrgent")) && StringUtils.isNotEmpty((String) condition.get("isUrgent"))) {
                srdEw.eq("b.is_urgent", condition.get("isUrgent").toString());
            }
            //指令发运时间
            if (Objects.nonNull(condition.get("startDate")) && StringUtils.isNotEmpty((String) condition.get("startDate"))) {
                srdEw.ge("b.ship_date", condition.get("startDate").toString());
            }
            if (Objects.nonNull(condition.get("endDate")) && StringUtils.isNotEmpty((String) condition.get("endDate"))) {
                srdEw.le("b.ship_date", condition.get("endDate").toString());
            }
            //指令创建时间
            if (Objects.nonNull(condition.get("shipStartDate")) && StringUtils.isNotEmpty((String) condition.get("shipStartDate"))) {
                srdEw.ge("b.gmt_create", condition.get("shipStartDate").toString());
            }
            if (Objects.nonNull(condition.get("shipEndDate")) && StringUtils.isNotEmpty((String) condition.get("shipEndDate"))) {
                srdEw.le("b.gmt_create", condition.get("shipEndDate").toString());
            }

            if (Objects.nonNull(condition.get("pointName")) && StringUtils.isNotEmpty((String) condition.get("pointName"))) {
                srdEw.like("c.name", condition.get("pointName").toString());
            }
            // queryType 查询类型（1:已发运；0未发运）
            String queryType = (String) condition.get("shipType");
            // 0表示待发运，1表示已发运
            if (TableStatusEnum.STATUS_0.getCode().equals(queryType)) {
                srdEw.isNull("b.real_ship_date");
            } else if (TableStatusEnum.STATUS_1.getCode().equals(queryType)) {
                srdEw.isNotNull("b.real_ship_date");
            }
            if (Objects.nonNull(condition.get("plateNumber")) && StringUtils.isNotEmpty((String) condition.get("plateNumber"))) {
                srdEw.like("a.plate_no", (String) condition.get("plateNumber"));
            }
            if (Objects.nonNull(condition.get("customerId")) && StringUtils.isNotEmpty((String) condition.get("customerId"))) {
                srdEw.like("b.customer_id", (String) condition.get("customerId"));
            }
            if (condition.containsKey("shipmentGid") && StringUtils.isNotEmpty((String) condition.get("shipmentGid"))) {
                List<String> shipmentList = Arrays.asList(CommonMethod.setVins((String) condition.get("shipmentGid")));
                srdEw.andNew().in("b.shipment_gid",shipmentList).or().like("b.shipment_gid", (String) condition.get("shipmentGid"));
            }
            if (Objects.nonNull(condition.get("cusWayBillNo")) && StringUtils.isNotEmpty((String) condition.get("cusWayBillNo"))) {
                List<String> shipmentList = Arrays.asList(CommonMethod.setVins((String) condition.get("cusWayBillNo")));
                srdEw.andNew().in("b.cus_waybill_no",shipmentList).or().like("b.cus_waybill_no", (String) condition.get("cusWayBillNo"));
            }
            if (Objects.nonNull(condition.get("releaseGid")) && StringUtils.isNotEmpty((String) condition.get("releaseGid"))) {
                List<String> releaseGids = Arrays.asList(CommonMethod.setVins((String) condition.get("releaseGid")));
                srdEw.andNew().in("b.release_gid",releaseGids).or().like("b.release_gid", (String) condition.get("releaseGid"));
            }
            if (Objects.nonNull(condition.get("vin")) && StringUtils.isNotEmpty((String) condition.get("vin"))) {
                List<String> vins = Arrays.asList(CommonMethod.setVins((String) condition.get("vin")));
                srdEw.andNew().in("b.vin", vins).or().like("b.vin", condition.get("vin").toString());
            }
        }
        srdEw.orderBy("b.gmt_modified", false);
    }

    /**
     * 更新运单状态为已发运
     * @param releaseList 运单列表
     * @param loginUser   登录用户信息
     * @param shipTime
     */
    public ArrayList<String> modifiedReleaseStatus (List<OtmReleaseForShipDTO> releaseList, User loginUser, String shipTime) {
        ArrayList<String> resultList = new ArrayList<>();
        ArrayList<StatusLog> insertLogs = Lists.newArrayList();
        StringBuffer sb = new StringBuffer();
        for (OtmReleaseForShipDTO oor : releaseList) {
            try {
                //1、是否标记为异常发运,标记为异常发运的车架号不能发运
                this.isExceptionDespatch(oor.getVin());

                //2、是否为已发运
                this.isShip(oor);

                //3、更新出库通知单车辆为已出库
                oor.setStatus(TableStatusEnum.STATUS_BS_DISPATCH.getCode());
                this.modifyOutbound(oor, loginUser.getName());

                //4、更新运单状态
                this.updateReleaseStatus(oor.getId(),shipTime,loginUser.getName());

                //5、新增状态日志表
                StatusLog sl = this.setStatusLog(loginUser.getName(), oor.getId(), TableStatusEnum.CHANNEL_PC.getCode());
                insertLogs.add(sl);

                //6、修改指令状态，并把已发运的数据同步到BMS/OTM
                this.passBackBMSAndOTM(oor,shipTime,loginUser.getName());
            } catch (Exception e) {
                sb.append("车架号:").append(oor.getVin()).append(":").append(e.getMessage());
                LOGGER.info("车架号{}发运失败！", oor.getVin());
            }
        }
        //7、statusLog 操作日志记录
        try {
            if (CollectionUtils.isNotEmpty(insertLogs)) {
                LOGGER.info("记录发运数据至status_log开始。。。。。。");
                statusLogService.insertBatch(insertLogs);
                LOGGER.info("记录发运数据至status_log结束。。。。。。");
            }
        } catch (Exception e) {
            LOGGER.info("pc单台发运日志记录异常！{}", e.getMessage());
        }
        if(StringUtils.isNotEmpty(sb)){
            resultList.add(sb.toString());
        }
        return resultList;
    }

    /**
     * 设置操作日志参数
     *
     * @param loginName 登录用户
     * @param oorId     release表的主键id
     */
    private StatusLog setStatusLog (String loginName, Long oorId,String channelType) {
        LOGGER.info("设置发运数据至status_log,release主键id为{}",oorId);
        StatusLog sl = new StatusLog();
        sl.setUserCreate(loginName);
        sl.setChannelType(channelType);
        sl.setTableId(String.valueOf(oorId));
        sl.setTableType(TableStatusEnum.STATUS_10.getCode());
        sl.setStatus(TableStatusEnum.STATUS_BS_DISPATCH.getCode());
        sl.setStatusName(TableStatusEnum.STATUS_BS_DISPATCH.getCode());
        return sl;
    }

    /**
     * 更新release表的状态
     *
     * @param id        主键id
     * @param shipTime
     * @param loginName 登录操作人
     */
    public void updateReleaseStatus (Long id, String shipTime, String loginName) {
        OtmOrderRelease release = new OtmOrderRelease();
        release.setId(id);
        release.setStatus(TableStatusEnum.STATUS_BS_DISPATCH.getCode());
        if (StringUtils.isNotEmpty(shipTime)) {
            release.setShipDate(this.getShipTme(shipTime));
        } else {
            release.setShipDate(new Date());
        }
        release.setRealShipDate(new Date());
        release.setShipUser(loginName);
        updateById(release);
        LOGGER.info("更新{}对应的release状态为已发运", id);
    }

    /**
     * 发运时间转换
     */
    public Date getShipTme (String shipTime) {
        Date date = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            date = formatter.parse(shipTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 查询是否已发运
     * @param oor
     */
    private void isShip (OtmReleaseForShipDTO oor) {
        Wrapper<OtmOrderRelease> param = new EntityWrapper<>();
        param.eq("id", oor.getId());
        param.eq("vin", oor.getVin());
        param.isNotNull("ship_date");
        int count = selectCount(param);
        LOGGER.info("运单【" + oor.getReleaseGid() + "】查询是否已发运结果：{}", count);
        if (count == 1) {
            throw new BaseException("运单" + oor.getReleaseGid() + " 对应的车架号 " + oor.getVin() + "已发运，无需重复发运");
        }
    }

    /**
     * 更改指令为已发运
     *
     * @param id 指令主键id
     */
    private void modifyShipmentStatus (Long id,String shipmentStatus,String channelType,String shipTime) {
        //明细已经全部发运/运抵
        OtmShipment os = new OtmShipment();
        os.setStatus(shipmentStatus);
        os.setId(id);
        if(StringUtils.isNotEmpty(shipTime)){
            os.setGmtModified(this.getShipTme(shipTime));
        }
        shipmentService.updateById(os);
        LOGGER.info("修改主键{}的shipment表的状态为已发运",os.getId());
    }

    /**
     * 更改指令状态并发送给OTM/BMS
     *  @param oor
     * @param shipTime
     * @param userName
     */
    public void passBackBMSAndOTM (OtmReleaseForShipDTO oor, String shipTime, String userName){
        //1、根据运单号获取指令信息
        Wrapper<OtmShipment> ew = new EntityWrapper<>();
        ew.eq("shipment_gid", oor.getShipmentGid());
        ew.ne("status", TableStatusEnum.STATUS_50.getCode());
        OtmShipment otmShipments = otmShipmentService.selectOne(ew);
        LOGGER.info(" 回传OTM/BMS根据{}查询的指令信息为：{}", oor.getReleaseGid(), otmShipments);
        if (null == otmShipments) {
            throw new BaseException("指令信息为空，请联系相关人员查询问题原因");
        }

          //运单状态已发运
        String releaseStatus = TableStatusEnum.STATUS_BS_DISPATCH.getCode();
        if (StringUtils.isNotBlank(otmShipments.getStatus()) && releaseStatus.equals(otmShipments.getStatus())) {
            throw new BaseException("运单" + oor.getReleaseGid() + "信息对应的指令状态为已发运，请联系相关人员查询问题原因");
        }

        //2、设置回传信息给OTM/BMS的参数
        ShipmentForShipDTO shipmentForShipDTO = new ShipmentForShipDTO();
        shipmentForShipDTO.setDriverGid(otmShipments.getDriverGid());
        shipmentForShipDTO.setServiceProviderGid(otmShipments.getServiceProviderGid());
        shipmentForShipDTO.setPlateNo(otmShipments.getPlateNo());
        shipmentForShipDTO.setTrailerNo(otmShipments.getTrailerNo());
        OtmOrderRelease otmRelease = this.setReleaseInfo(oor);

        //3、调整头表发运状态 增加判断明细都为已发运
        EntityWrapper<OtmOrderRelease> oorEW = new EntityWrapper<>();
        oorEW.eq("shipment_gid", oor.getShipmentGid());
        oorEW.isNull("ship_date");
        oorEW.ne("status", TableStatusEnum.STATUS_50.getCode());
        int notShipCount = otmOrderReleaseService.selectCount(oorEW);
        //得到当前指令状态
        String status = otmShipments.getStatus();
        //如果当前指令状态为已入库状态，则shipStatusResult为false，不进行下面指令状态更改的动作
        Boolean shipStatusResult = updateShipStatus(status);
        if (notShipCount == 0 && shipStatusResult) {
            this.modifyShipmentStatus(otmShipments.getId(),TableStatusEnum.STATUS_BS_DISPATCH.getCode(),TableStatusEnum.CHANNEL_PC.getCode(),shipTime);
        }

        //4、回传信息给OTM/BMS
        LOGGER.info("回传OTM入参shipmentForShipDTO：{},入参otmRelease：{}",shipmentForShipDTO.toString(),otmRelease.toString());
        integrationService.toOtmBms(shipmentForShipDTO, otmRelease,shipTime,userName);
    }

    //在进行指令更改前先判断指令状态，如果是确认发运时指令已经是入库状态，则指令状态不更改
    public Boolean updateShipStatus(String status) {
        if (StringUtils.isBlank(status)) {
            return true;
        }
        else if (status.equals(TableStatusEnum.STATUS_BS_INBOUND.getCode())) {
            return false;
        } else {
            return true;
        }
    }

    private OtmOrderRelease setReleaseInfo (OtmReleaseForShipDTO oor) {
        OtmOrderRelease otmOrderRelease = new OtmOrderRelease();
        otmOrderRelease.setVin(oor.getVin());
        otmOrderRelease.setStanVehicleType(oor.getStanVehicleType());
        otmOrderRelease.setOriginLocationProvince(oor.getOriginLocationProvince());
        otmOrderRelease.setOriginLocationCity(oor.getOriginLocationCity());
        otmOrderRelease.setOriginLocationCounty(oor.getOriginLocationCounty());
        otmOrderRelease.setOriginLocationAddress(oor.getOriginLocationAddress());
        otmOrderRelease.setDestLocationProvince(oor.getDestLocationProvince());
        otmOrderRelease.setDestLocationCity(oor.getDestLocationCity());
        otmOrderRelease.setDestLocationCounty(oor.getDestLocationCounty());
        otmOrderRelease.setDestLocationAddress(oor.getDestLocationAddress());
        otmOrderRelease.setOriginLocationGid(oor.getOriginLocationGid());
        otmOrderRelease.setDestLocationGid(oor.getDestLocationGid());
        otmOrderRelease.setCusOrderNo(oor.getCusOrderNo());
        otmOrderRelease.setCusWaybillNo(oor.getCusWaybillNo());
        otmOrderRelease.setId(oor.getId());
        otmOrderRelease.setShipmentGid(oor.getShipmentGid());
        otmOrderRelease.setReleaseGid(oor.getReleaseGid());
        return otmOrderRelease;
    }

    /**
     * 更新出库通知单状态
     *
     * @param oor  运单信息
     * @param loginName 登录用户名
     */
    public void modifyOutbound (OtmReleaseForShipDTO oor, String loginName) {
        ArrayList<String> status = Lists.newArrayList();
        status.add(TableStatusEnum.STATUS_10.getCode());
        status.add(TableStatusEnum.STATUS_20.getCode());
        EntityWrapper<OutboundNoticeLine> nlEW = new EntityWrapper<>();
        nlEW.eq("line_source_key", oor.getReleaseGid()).in("status", status).orderBy("id", false);
        OutboundNoticeLine noticeLine = outboundNoticeLineService.selectOne(nlEW);
        if (noticeLine != null) {
            //调用方法出库
            outboundShipLineService.shipByNoticeLineId(noticeLine.getId(), PutAwayType.NOTICE_PUTAWAY, SourceSystem.AUTO);
            //调用方法修改备料状态
            prepareHeaderService.updatePrepareFinishByLineId(noticeLine.getId(), loginName);
        }
    }

    /**
     * 是否异常发运
     *
     * @param re_vin 车架号
     */
    private void isExceptionDespatch (String re_vin) {
        Wrapper<ExceptionRegister> registerWrapper = new EntityWrapper<>();
        registerWrapper.eq("vin", re_vin).eq("otm_status", TableStatusEnum.STATUS_N.getCode());
        ExceptionRegister exceptionRegister = exceptionRegisterService.selectOne(registerWrapper);
        LOGGER.info("车架号【" + re_vin + "】是否标记异常发运结果：{}", exceptionRegister == null ? exceptionRegister : exceptionRegister.toString());
        if (Objects.nonNull(exceptionRegister)) {
            throw new BaseException("车架号" + re_vin + "异常不发运,请联系调度!");
        }

    }

    /**
     * 根据运单id获取运单信息，并查询状态是否为已发运，已发运的运单无需再次发运
     *
     * @param releaseIds 运单id
     * @return 运单信息
     * @deprecated is_ship 需发运(0:否,1:是)
     */
    private List<OtmReleaseForShipDTO> queryOtmReleaseList (String releaseIds, String userCode) {
        //关联运单 启运地(多个发运地,需要多个发车点确认发运)
        EntityWrapper<OtmReleaseForShipDTO> ew = new EntityWrapper<>();
        ew.in("releaseId", releaseIds.split(","))
                .eq("userCode", userCode)
                .eq("is_ship", TableStatusEnum.STATUS_1.getCode())
                .ne("releaseStatus", TableStatusEnum.STATUS_50.getCode())
                .orderBy("re_gmt_modify", false)
                .orderBy("releaseId", false);
        List<OtmReleaseForShipDTO> list = otmShipmentMapper.queryOtmReleaseList(ew);
        if (CollectionUtils.isEmpty(list)) {
            throw new BaseException("未查询到对应的运单信息");
        }
        return list;
    }
}
